/*****************************************************************************
 *   Copyright 2005 Tim A Wang
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 ****************************************************************************/
package com.jb.web.renderer;

import com.jb.faces.component.UIComponent;
import com.jb.faces.context.ResponseStream;
import com.jb.faces.context.ResponseWriter;
import com.jb.faces.render.RenderKit;
import com.jb.faces.render.Renderer;
import com.jb.faces.render.ResponseStateManager;
import com.jb.framework.Registry;
import com.jb.util.ClassUtil;
import com.jb.web.bean.JBTreeNode;
import com.jb.web.bean.custom.GeoMap;
import com.jb.web.bean.custom.Rater;
import com.jb.web.bean.custom.renderer.GeoMapRenderer;
import com.jb.web.bean.list.Paginator;
import com.jb.web.bean.list.PagingRenderer;
import com.jb.web.context.ResponseWriterImpl;

import java.io.OutputStream;

import java.util.ArrayList;
import java.util.List;


public class RenderKitImpl extends RenderKit {
    static private Registry rendererRegistiry = new Registry() {
            public boolean testRegistration(Object pRegistered, Object pTestObj) {
                if (!(pRegistered instanceof Class)) {
                    return false;
                }

                return pRegistered.equals(pTestObj);
            }
        };

    static private Registry rendererCache = new Registry() {
            public boolean testRegistration(Object pRegistered, Object pTestObj) {
                if (!(pRegistered instanceof Class)) {
                    return false;
                }

                return pRegistered.equals(pTestObj);
            }
        };

    static {
        registerRenderer(com.jb.web.bean.custom.Timer.class, TimerRenderer.class);
        registerRenderer(com.jb.web.bean.FloatPanel.class, FloatPanelRenderer.class);
        registerRenderer(com.jb.web.bean.TableCell.class, TableCellRenderer.class);

        registerRenderer(com.jb.web.bean.database.DatabaseTable.class, ListBeanRenderer.class);
        registerRenderer(com.jb.web.bean.ListBean.class, ListBeanRenderer.class);

        registerRenderer(com.jb.web.bean.InternalFrame.class, InternalFrameRenderer.class);

        registerRenderer(com.jb.web.bean.TableRow.class, TableRowRenderer.class);
        registerRenderer(com.jb.web.bean.TableHeader.class, TableRowRenderer.class);

        registerRenderer(com.jb.web.bean.TabbedPanel.class, TabStripRenderer.class);
        registerRenderer(com.jb.web.bean.Page.class, PageLayoutManager.class);
        registerRenderer(com.jb.web.bean.Panel.class, FlowLayoutManager.class);

        registerRenderer(com.jb.web.bean.Form.class, TableFormRenderer.class);
        registerRenderer(com.jb.web.form.BeanForm.class, BeanFormRenderer.class);

        registerRenderer(com.jb.web.bean.Label.class, TextRenderer.class);
        registerRenderer(com.jb.web.bean.Paragraph.class, ParagraphRenderer.class);

        registerRenderer(com.jb.web.bean.inspector.PropertyInspector.class, TableFormRenderer.class);

        registerRenderer(com.jb.web.bean.inspector.PropertyField.class, PropertyEditorRenderer.class);
        registerRenderer(com.jb.web.bean.SecretTextField.class, PasswordFieldRenderer.class);
        registerRenderer(com.jb.web.bean.DateTextField.class, DateFieldRenderer.class);
        registerRenderer(com.jb.web.bean.TextField.class, TextFieldRenderer.class);
        registerRenderer(com.jb.web.bean.FormField.class, TextFieldRenderer.class);

        registerRenderer(com.jb.web.bean.Button.class, ButtonRenderer.class);
        registerRenderer(com.jb.web.bean.TextArea.class, TextAreaRenderer.class);
        registerRenderer(com.jb.web.bean.Select.class, SelectRenderer.class);
        registerRenderer(com.jb.web.bean.CheckBox.class, CheckBoxRenderer.class);
        registerRenderer(com.jb.web.bean.RadioButton.class, RadioButtonRenderer.class);

        registerRenderer(com.jb.web.bean.Link.class, LinkRenderer.class);

        registerRenderer(com.jb.web.bean.Menu.class, MenuItemRenderer.class);
        registerRenderer(com.jb.web.bean.MenuItem.class, MenuItemRenderer.class);
        registerRenderer(com.jb.web.bean.Image.class, ImageRenderer.class);
        registerRenderer(com.jb.web.bean.Table.class, TableRenderer.class);

        registerRenderer(com.jb.web.bean.FileUpload.class, UploaderRenderer.class);
        registerRenderer(com.jb.web.bean.custom.WebCalendar.class, CalenderRenderer.class);

        registerRenderer(com.jb.web.model.AbstractVariable.class, ComponentRenderer.class);
        registerRenderer(Rater.class, com.jb.web.bean.custom.renderer.RaterRenderer.class);
        registerRenderer(Paginator.class, PagingRenderer.class);
        registerRenderer(GeoMap.class, GeoMapRenderer.class);
        registerRenderer(JBTreeNode.class, TreeNodeRenderer.class);
    }

    /**
     * Gets a list of renderers that could render the been class, includes
     * all the renderers regiester for this class, and all its super classes.
     *
     * @param compType parameter
     *
     * @return return-value
     */
    public static List getRenderTypes(Class compType) {
        ArrayList list = new ArrayList();
        List rendererList = rendererRegistiry.getRegisteredValues(compType);

        if (rendererList != null) {
            list.addAll(rendererList);
        }

        if ((compType != null) && (compType.getSuperclass() != Object.class)) {
            list.addAll(getRenderTypes(compType.getSuperclass()));
        }

        return list;
    }

    /**
     * Returns a render for a given component.
     */
    public List<Renderer> getRenderer(String family, String rendererType)    {
        return null;
    }
    
    public static Renderer getRenderer(UIComponent pComponent) {
        List list = rendererCache.getRegisteredValues(pComponent.getClass());

        String renderType = pComponent.getRendererType();
        if (list != null) {
            for (int i = 0; i < list.size(); i++) {
                RendererImpl renderer = (RendererImpl) list.get(i);

                if (renderer.getClass().getName().equals(renderType)) {
                    return renderer;
                }
            }
        }

        Class renderClass = null;

        try {
            if ((renderType == null) || (renderType.length() == 0)) {
                list = getRenderTypes(pComponent.getClass());

                if ((list != null) && (list.size() > 0)) {
                    renderClass = (Class) list.get(0);
                    pComponent.setRendererType(renderClass.getName());
                }
            } else {
                renderClass = ClassUtil.getClass(renderType);
                if(renderClass==null)
                    return new DefaultRenderer();
            }

            if (renderClass != null) {
                RendererImpl renderer = (RendererImpl) renderClass.newInstance();
                rendererCache.register(pComponent.getClass(), renderer);

                return renderer;
            }
        } catch (Exception e) {
            System.err.print("Renderer " + renderType + " can not be initialized");
        }

        return new DefaultRenderer();
    }

    public static RendererImpl createRenderer(String rendererName) {
        return(RendererImpl)  ClassUtil.createInstance(rendererName);
    }

    /**
     *
     * @param renderType parameter
     * @param rendererClass parameter
     */
    public static void registerRenderer(Class renderType, Class rendererClass) {
        rendererRegistiry.register(renderType, rendererClass);
    }


    public ResponseStateManager getResponseStateManager() {
        return null;
    }

    public void addRenderer(String family, String rendererType, Renderer renderer) {
    }

    public ResponseStream createResponseStream(OutputStream out) {
        return null;
    }

    public ResponseWriter createResponseWriter(java.io.Writer writer, java.lang.String contentTypeList,
        java.lang.String characterEncoding) {
        return new ResponseWriterImpl(writer, contentTypeList, characterEncoding);
    }
}
